
#include "AbstractTree.h"

// [*] and_or_tree::CAbstractNode

int and_or_tree::CAbstractNode::GetChildrenAmount() const
{
	return (int)ChildrenIndexList.Size;
}

const int* and_or_tree::CAbstractNode::GetPtrChildrenIndex() const
{
	return ChildrenIndexList.pElement;
}

int and_or_tree::CAbstractNode::GetSubTreeLeafNodeAmount() const
{
	return (int)NodeIndexOfSubTreeLeafNodeList.Size;
}

const int* and_or_tree::CAbstractNode::GetPtrNodeIndexOfSubTreeLeafNode() const
{
	return NodeIndexOfSubTreeLeafNodeList.pElement;
}

const int* and_or_tree::CAbstractNode::GetPtrLeafIndexOfSubTreeLeafNode() const
{
	return LeafIndexOfSubTreeLeafNodeList.pElement;
}

// [*] and_or_tree::COrNode

int and_or_tree::COrNode::GetType() const
{
	return TYPE_OR;
}

int and_or_tree::COrNode::GetShapeFeatureDimension() const
{
	return 0;
}

int and_or_tree::COrNode::GetAppearanceFeatureDimension() const
{
	return 0;
}

void and_or_tree::COrNode::ComputeShapeFeature(
	CSimpleTypeArray<double>& DstShapeFeatureList,
	const CParsedInstance* pSrcMyInstance,
	const CSimpleTypeArray<const CParsedInstance*>& SrcChildrenInstancePtrList
	) const
{
	DstShapeFeatureList.Clear();
}

void and_or_tree::COrNode::ComputeAppearanceFeature(
	CSimpleTypeArray<double>& DstAppearanceFeatureList,
	const CParsedInstance* pSrcMyInstance
	) const
{
	DstAppearanceFeatureList.Clear();
}

//void and_or_tree::COrNode::ExtractParsedInstance(
//	CParsedInstance* pDstParsedInstance,
//	const CSimpleTypeArray<const CParsedInstance*>& ChildrenPiptrList
//	) const
//{
//	int i;
//	const CParsedInstance * const * qqpi;
//	pDstParsedInstance->ClearAll();
//
//	if ((int)ChildrenPiptrList.Size < 1) return;
//
//	qqpi = ChildrenPiptrList.pElement;
//	*pDstParsedInstance = **(qqpi++);
//	for ( i = 1; i < (int)ChildrenPiptrList.Size; ++i, ++qqpi )
//	{
//		if (pDstParsedInstance->tree_total_score < (*qqpi)->tree_total_score) continue;
//		*pDstParsedInstance = **qqpi;
//	}
//}

// [*] and_or_tree::CAndNode

int and_or_tree::CAndNode::GetType() const
{
	return TYPE_AND;
}

int and_or_tree::CAndNode::GetShapeFeatureDimension() const
{
	return 12;
}

int and_or_tree::CAndNode::GetAppearanceFeatureDimension() const
{
	return 0;
}

void and_or_tree::CAndNode::ComputeShapeFeature(
	CSimpleTypeArray<double>& DstShapeFeatureList,
	const CParsedInstance* pSrcMyInstance,
	const CSimpleTypeArray<const CParsedInstance*>& SrcChildrenInstancePtrList
	) const
{
	DstShapeFeatureList.Clear();

	double		ori12, ori23, ori31;
	double		d12, d23, d31, sum, t;

	const CParsedInstance* pNode1 = SrcChildrenInstancePtrList.pElement[0];
	const CParsedInstance* pNode2 = SrcChildrenInstancePtrList.pElement[1];
	const CParsedInstance* pNode3 = SrcChildrenInstancePtrList.pElement[2];

	d12		= sqrt(CMyMath::sqr(pNode1->x - pNode2->x) + CMyMath::sqr(pNode1->y - pNode2->y)); if (d12 < 1.0) d12 = 1.0;
	d23		= sqrt(CMyMath::sqr(pNode2->x - pNode3->x) + CMyMath::sqr(pNode2->y - pNode3->y)); if (d12 < 1.0) d23 = 1.0;
	d31		= sqrt(CMyMath::sqr(pNode3->x - pNode1->x) + CMyMath::sqr(pNode3->y - pNode1->y)); if (d12 < 1.0) d31 = 1.0;
	sum		= d12 + d23 + d31;

	ori12	= atan2(pNode2->y - pNode1->y, pNode2->x - pNode1->x); // ((pNode2->y > pNode1->y) ? +1 : -1) * acos((pNode2->x - pNode1->x) / d12);
	ori23	= atan2(pNode3->y - pNode2->y, pNode3->x - pNode2->x); // ((pNode2->y > pNode1->y) ? +1 : -1) * acos((pNode2->x - pNode1->x) / d12);
	ori31	= atan2(pNode1->y - pNode3->y, pNode1->x - pNode3->x); // ((pNode2->y > pNode1->y) ? +1 : -1) * acos((pNode2->x - pNode1->x) / d12);

	DstShapeFeatureList.PushBack(pNode1->rotation - ori12);
	DstShapeFeatureList.PushBack(pNode2->rotation - ori23);
	DstShapeFeatureList.PushBack(pNode3->rotation - ori31);
	DstShapeFeatureList.PushBack(PI + ori31 - ori12);
	DstShapeFeatureList.PushBack(PI + ori12 - ori23);
	DstShapeFeatureList.PushBack(PI + ori23 - ori31);

	DstShapeFeatureList.PushBack(d12 * 3.0 / sum);
	DstShapeFeatureList.PushBack(d23 * 3.0 / sum);
	DstShapeFeatureList.PushBack(d31 * 3.0 / sum);
	//t = fabs(pNode1->scale - pNode2->scale); DstShapeFeatureList.PushBack(t);
	//t = fabs(pNode2->scale - pNode3->scale); DstShapeFeatureList.PushBack(t);
	//t = fabs(pNode3->scale - pNode1->scale); DstShapeFeatureList.PushBack(t);
	t = fabs(pNode1->scale - pNode2->scale); DstShapeFeatureList.PushBack(exp(t));
	t = fabs(pNode2->scale - pNode3->scale); DstShapeFeatureList.PushBack(exp(t));
	t = fabs(pNode3->scale - pNode1->scale); DstShapeFeatureList.PushBack(exp(t));
}

void and_or_tree::CAndNode::ComputeAppearanceFeature(
	CSimpleTypeArray<double>& DstAppearanceFeatureList,
	const CParsedInstance* pSrcMyInstance
	) const
{
	DstAppearanceFeatureList.Clear();
}

//void and_or_tree::CAndNode::ExtractParsedInstance(
//	CParsedInstance* pDstParsedInstance,
//	const CSimpleTypeArray<const CParsedInstance*>& ChildrenPiptrList
//	) const
//{
//	int i;
//	const CParsedInstance * const * qqpi;
//	pDstParsedInstance->ClearAll();
//
//	if ((int)ChildrenPiptrList.Size < 1) return;
//
//	qqpi = ChildrenPiptrList.pElement;
//	for ( i = 0; i < (int)ChildrenPiptrList.Size; ++i, ++qqpi )
//	{
//		pDstParsedInstance->x += (*qqpi)->x;
//		pDstParsedInstance->y += (*qqpi)->y;
//		pDstParsedInstance->rotation += (*qqpi)->rotation;
//		pDstParsedInstance->scale += (*qqpi)->scale;
//	}
//
//	pDstParsedInstance->x /= (int)ChildrenPiptrList.Size;
//	pDstParsedInstance->y /= (int)ChildrenPiptrList.Size;
//	pDstParsedInstance->rotation /= (int)ChildrenPiptrList.Size;
//	pDstParsedInstance->scale /= (int)ChildrenPiptrList.Size;
//}

// [*] and_or_tree::CLeafNode

CImagePositionFeatureExtractor* and_or_tree::CLeafNode::pIPFE_Prototype = NULL;
int and_or_tree::CLeafNode::AppearanceFeatureDimension = 0;
CImagePyramidPositionFeatureExtractor* and_or_tree::CLeafNode::pCurrentIPPFE = NULL;

void and_or_tree::CLeafNode::InitIPFE(CImagePositionFeatureExtractor* pInitialized_IPFE_Prototype)
{
	pIPFE_Prototype = pInitialized_IPFE_Prototype;
	if (pIPFE_Prototype)
		AppearanceFeatureDimension = pIPFE_Prototype->GetFeatureDimension();
	else
		AppearanceFeatureDimension = 0;
}

void and_or_tree::CLeafNode::SetCurrentIPPFE(CImagePyramidPositionFeatureExtractor* pIPPFE)
{
	pCurrentIPPFE = pIPPFE;
}

int and_or_tree::CLeafNode::GetType() const
{
	return TYPE_LEAF;
}

int and_or_tree::CLeafNode::GetShapeFeatureDimension() const
{
	return 0;
}

int and_or_tree::CLeafNode::GetAppearanceFeatureDimension() const
{
	return AppearanceFeatureDimension;
}

void and_or_tree::CLeafNode::ComputeShapeFeature(
	CSimpleTypeArray<double>& DstShapeFeatureList,
	const CParsedInstance* pSrcMyInstance,
	const CSimpleTypeArray<const CParsedInstance*>& SrcChildrenInstancePtrList
	) const
{
	DstShapeFeatureList.Clear();
}

void and_or_tree::CLeafNode::ComputeAppearanceFeature(
	CSimpleTypeArray<double>& DstAppearanceFeatureList,
	const CParsedInstance* pSrcMyInstance
	) const
{
	int i;
	CImagePyramidPosition ipp;
	
#if AND_OR_TREE_FEATURE_MODE
#else
	ipp.InitNew(pSrcMyInstance->x, pSrcMyInstance->y, 1.0, 1.0);
	pCurrentIPPFE->SetQuery(ipp);
#endif

	DstAppearanceFeatureList.Resize(AppearanceFeatureDimension);
	double* pd = DstAppearanceFeatureList.pElement;
	for ( i = 0; i < AppearanceFeatureDimension; ++i )
		*(pd++) = pCurrentIPPFE->GetFeature(i);
}

//void and_or_tree::CLeafNode::ExtractParsedInstance(
//	CParsedInstance* pDstParsedInstance,
//	const CSimpleTypeArray<const CParsedInstance*>& ChildrenPiptrList
//	) const
//{
//	pDstParsedInstance->ClearAll();
//}

// [*] and_or_tree::CAbstractTree

void and_or_tree::CAbstractTree::myRelease()
{
	LayerAmount = 0;
	CDataStructureTools::ReleasePointers(PtrNodeList);
	LayerStartList.Clear(); LayerStartList.PushBack(0);
}

and_or_tree::CAbstractTree::CAbstractTree()
{
	LayerAmount = 0;
	PtrNodeList.Clear();
	LayerStartList.Clear(); LayerStartList.PushBack(0);
}

and_or_tree::CAbstractTree::~CAbstractTree()
{
	myRelease();
}

bool and_or_tree::CAbstractTree::Is_A_AncestorOf_B(int A, int B) const
{
	if (A<0 || A>=NodeAmount || B<0 || B>=NodeAmount) return false;
	return AreAncestorRelation.pElement[B + A * NodeAmount];
}

const int* and_or_tree::CAbstractTree::GetPtrLeafNodeIndex() const
{
	return LeafNodeIndexList.pElement;
}

int and_or_tree::CAbstractTree::GetRootIndex() const
{
	return 0;
}

int and_or_tree::CAbstractTree::GetNodeIndex(int LayerIndex, int NodeIndexInLayer) const
{
	if (LayerIndex<0 || LayerIndex>=LayerAmount) return -1;
	const int* qls = LayerStartList.pElement + LayerIndex;
	int ls = *qls;
	int la = *(++qls) - ls;
	if (NodeIndexInLayer<0 || NodeIndexInLayer>=la) return -1;
	return ls + NodeIndexInLayer;
}

int and_or_tree::CAbstractTree::GetLeafNodeIndex(int LeafIndex) const
{
	if (LeafIndex<0 || LeafIndex>=LeafNodeAmount) return -1;
	return LeafNodeIndexList.pElement[LeafIndex];
}

const and_or_tree::CAbstractNode* and_or_tree::CAbstractTree::GetNode(int NodeIndex) const
{
	if (NodeIndex<0 || NodeIndex>=NodeAmount) return NULL;
	return PtrNodeList.pElement[NodeIndex];
}

const and_or_tree::CAbstractNode* and_or_tree::CAbstractTree::GetRoot() const
{
	return GetNode(GetRootIndex());
}

const and_or_tree::CAbstractNode* and_or_tree::CAbstractTree::GetNode(int LayerIndex, int NodeIndexInLayer) const
{
	return GetNode(GetNodeIndex(LayerIndex, NodeIndexInLayer));
}

//int and_or_tree::CAbstractTree::GetNodeEdgeIndexBase(int NodeIndex) const
//{
//	if (NodeIndex<0 || NodeIndex>=NodeAmount) return -1;
//	return EdgeIndexBase.pElement[NodeIndex];
//}

void and_or_tree::CAbstractTree::myInit(string strFN_AbstractTree)
{
	int i,j,o,t,jbase,jj,oo;
	bool fIsLeaf;
	char strTemp[10001];
	int* plsl;

	myRelease();

	ifstream inFile(strFN_AbstractTree.c_str());

	inFile>>LayerAmount;
	LayerStartList.Resize(LayerAmount + 1);
	plsl = LayerStartList.pElement; *plsl = 0;
	for ( i = 0; i < LayerAmount; ++i )
	{
		inFile>>t;
		*(plsl+1) = t + *plsl;
		++plsl;
	}

	PtrNodeList.Resize(NodeAmount = *plsl);
	LeafNodeIndexList.Clear();
	AreAncestorRelation.Resize(NodeAmount * NodeAmount);
	AreAncestorRelation.Fill(false);
	//EdgeIndexBase.Clear(); EdgeIndexBase.PushBack(EdgeAmount = 0);

	int tr, tg, tb;
	int sr, sg, sb;
	int Z = 31;
	int M = (255 + Z - 1) / Z * Z;

	tr = M; tg = tb = 0;
	sr = 0; sg = +1; sb = 0;

	NodeColorList.Clear();
	for ( i = 0; ; ++i ) // for ( i = 0; i < NodeAmount; ++i )
	{
		tr += Z * sr;
		tg += Z * sg;
		tb += Z * sb;
		
		if (sg==+1 && tg>=M) { sr = -1; sg = 0; sb = 0; }
		if (sr==-1 && tr<=0) { sr = 0; sg = 0; sb = +1; }
		if (sb==+1 && tb>=M) { sr = 0; sg = -1; sb = 0; }
		if (sg==-1 && tg<=0) { sr = +1; sg = 0; sb = 0; }
		if (sr==+1 && tr>=M) { sr = 0; sg = 0; sb = -1; }
		if (sb==-1 && tb<=0) break;

		NodeColorList.PushBack(TranslateColor(
			tr + (255 - M) / 2,
			tg + (255 - M) / 2,
			tb + (255 - M) / 2));
	}

	for ( i = 0; i < LayerAmount; ++i )
	{
		jbase = LayerStartList.pElement[i];
		jj = LayerStartList.pElement[i+1] - jbase;
		for ( j = 0; j < jj; ++j )
		{
			CAbstractNode* pNode;

			inFile>>strTemp;
			fIsLeaf = false;
			if (strTemp[0] == '|')
				pNode = new COrNode();
			else if (strTemp[0] == '&')
				pNode = new CAndNode();
			else
			{
				pNode = new CLeafNode();
				fIsLeaf = true;
			}

			PtrNodeList.pElement[jbase + j] = pNode;

			pNode->NodeIndex = jbase + j;
			pNode->LayerIndex = i;
			pNode->IndexInLayer = j;
			pNode->ChildrenIndexList.Clear();
			pNode->NodeIndexOfSubTreeLeafNodeList.Clear();
			pNode->LeafIndexOfSubTreeLeafNodeList.Clear();

			if (fIsLeaf)
				LeafNodeIndexList.PushBack(pNode->NodeIndex);
			else
			{
				inFile>>oo;
				EdgeAmount += oo;
				for ( o = 0; o < oo; ++o )
				{
					plsl = LayerStartList.pElement + i + 1;
					for ( ; ; )
					{
						inFile>>t;
						if (t<0) ++plsl; else break;
					}
					pNode->ChildrenIndexList.PushBack(t + *plsl);

					AreAncestorRelation.pElement[(t + *plsl) + pNode->NodeIndex * NodeAmount] = true;
				}
			}

			//EdgeIndexBase.PushBack(EdgeAmount);
		}
	}

	LeafNodeAmount = (int)LeafNodeIndexList.Size;
	
	for ( i = 0; i < NodeAmount; ++i ) for ( j = 0; j < NodeAmount; ++j )
	{
		if (!AreAncestorRelation.pElement[j + i * NodeAmount]) continue;
		for ( o = 0; o < NodeAmount; ++o )
			AreAncestorRelation.pElement[j + o * NodeAmount] |= AreAncestorRelation.pElement[i + o * NodeAmount];
	}

	const int* qlni = GetPtrLeafNodeIndex();
	for ( i = 0; i < NodeAmount; ++i ) for ( j = 0; j < LeafNodeAmount; ++j )
		if (i==qlni[j] || Is_A_AncestorOf_B(i, qlni[j]))
		{
			PtrNodeList.pElement[i]->NodeIndexOfSubTreeLeafNodeList.PushBack(qlni[j]);
			PtrNodeList.pElement[i]->LeafIndexOfSubTreeLeafNodeList.PushBack(j);
		}

	inFile.clear();
	inFile.close();
}

int and_or_tree::CAbstractTree::TranslateColor(int R, int G, int B)
{
	R = (R<0 ? 0 : (R>255 ? 255 : R));
	G = (G<0 ? 0 : (G>255 ? 255 : G));
	B = (B<0 ? 0 : (B>255 ? 255 : B));
	return ((R<<16) | (G<<8) | B);
}

int and_or_tree::CAbstractTree::GetNodeColor(int NodeIndex) const
{
	if (NodeIndex<0 || NodeIndex>=NodeAmount) return 0;
	return NodeColorList.pElement[NodeIndex % NodeColorList.Size];
}

